/*
*****************************************************************************
* COPYRIGHT AND WARRANTY INFORMATION
*
* Copyright 2002-2012, Advanced Audio Video Coding Standard, Part II
*
* DISCLAIMER OF WARRANTY
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY.
* The AVS Working Group doesn't represent or warrant that the programs
* furnished here under are free of infringement of any third-party patents.
* Commercial implementations of AVS, including shareware, may be
* subject to royalty fees to patent holders. Information regarding
* the AVS patent policy for standardization procedure is available at
* AVS Web site http://www.avs.org.cn. Patent Licensing is outside
* of AVS Working Group.
*
* The Initial Developer of the Original Code is Video subgroup of AVS
* Workinggroup.
* Contributors: Qin Yu,         Zhichu He,  Weiran Li,    Yong Ling,
*               Zhenjiang Shao, Jie Chen,   Junjun Si,    Xiaozhen Zheng, 
*               Jian Lou,       Qiang Wang, Jianwen Chen, Haiwu Zhao,
*               Guoping Li,     Siwei Ma,   Junhao Zheng, Zhiming Wang
*               Li Zhang,
******************************************************************************
*/



/*!
***********************************************************************
*  \mainpage
*     This is the AVS decoder reference software. For detailed documentation
*     see the comments in each file.
*
*  \author
*     The main contributors are listed in contributors.h
*
*
*  \note
*     tags are used for document system "doxygen"
*     available at http://www.doxygen.org
*
*  \par Limitations:
*     Using different NAL's the assignment of partition-id to containing
*     syntax elements may got lost, if this information is not transmitted.
*     The same has to be stated for the partitionlength if partitions are
*     merged by the NAL.
*  \par
*     The presented solution in Q15-K-16 solves both of this problems as the
*     departitioner parses the bitstream before decoding. Due to syntax element
*     dependencies both, partition bounds and partitionlength information can
*     be parsed by the departitioner.
*
*  \par Handling partition information in external file:
*     As the TML is still a work in progress, it makes sense to handle this
*     information for simplification in an external file, here called partition
*     information file, which can be found by the extension .dp extending the
*     original encoded AVS bitstream. In this file partition-ids followed by its
*     partitionlength is written. Instead of parsing the bitstream we get the
*     partition information now out of this file.
*     This information is assumed to be never sent over transmission channels
*     (simulation scenarios) as it's information we allways get using a
*     "real" departitioner before decoding
*
*  \par Extension of Interim File Format:
*     Therefore a convention has to be made within the interim file format.
*     The underlying NAL has to take care of fulfilling these conventions.
*     All partitions have to be bytealigned to be readable by the decoder,
*     So if the NAL-encoder merges partitions, >>this is only possible to use the
*     VLC structure of the AVS bitstream<<, this bitaligned structure has to be
*     broken up by the NAL-decoder. In this case the NAL-decoder is responsable to
*     read the partitionlength information from the partition information file.
*     Partitionlosses are signaled with a partition of zero length containing no
*     syntax elements.
*
*/

/*
*************************************************************************************
* File name: ldecod.c
* Function: TML decoder project main()
*
*************************************************************************************
*/ 

#include "../../lcommon/inc/contributors.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/timeb.h>
#include <assert.h>

#if defined WIN32
#include <conio.h>
#include <IO.H>
#include <FCNTL.H>
#endif
#include "../../lcommon/inc/defines.h"
#include "global.h"
#include "../../lcommon/inc/commonVariables.h"
#include "../../lcommon/inc/memalloc.h"

#include "annexb.h"
#include "header.h"
#include "AEC.h"
#if ALF
#include "../../lcommon/inc/ComAdaptiveLoopFilter.h"
#include "../../ldecod/inc/DecAdaptiveLoopFilter.h"
#endif
#if ROI_M3264
#include "pos_info.h"
#endif

// Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION
#include "wquant.h"
#endif


#if MULTIVIEW_CODING
#define VIEW_LOGFILE	"texture_log.dec"
#define DEPTH_LOGFILE	"depth_log.dec"
#endif

#define LOGFILE     "log.dec"
#define DATADECFILE "dataDec.txt"
#define TRACEFILE   "trace_dec.txt"

#define _S_IREAD        0000400         /* read permission, owner */
#define _S_IWRITE       0000200         /* write permission, owner */

extern FILE* bits;

struct inp_par    *input;       //!< input parameters from input configuration file
SNRParameters    *snr;         //!< statistics
ImageParameters    *img;         //!< image parameters
StatBits *StatBitsPtr;

Bitstream *currStream;
FILE *reffile, *reffile2;

#if MULTIVIEW_CODING
SNRParameters   multiView_snrs[MAX_VIEW];
SNRParameters   multiView_depth_snrs[MAX_VIEW];

StatBits		multiView_StatBits[MAX_VIEW];
StatBits		multiView_depth_StatBits[MAX_VIEW];

#if MULTIVIEW_CODING
void initFileNames(char* dstStr, char* srcStr, int currView);
#endif

void multiView_openfile ()
{
	int i;
	int viewnumber = input->view_number;
	for( i = 0; i < viewnumber; i ++)
	{
#ifdef WIN32

		if ( input->output_dec_pic ) //output_dec_pic
		{
			if ( ( p_multiView_out[i] = _open ( input->outfile[i], _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE ) ) == -1 )
#else
		if ( input->output_dec_pic ) //output_dec_pic
		{
			if ( ( p_out = fopen ( input->outfile, "wb" ) ) == 0 )
#endif
			{
				snprintf ( errortext, ET_SIZE, "Error Open File %s ", input->outfile );
				error ( errortext, 500 );
			}
		}

#ifdef WIN32
		if ( ( p_multiView_ref[i] = _open ( input->reffile[i], O_RDWR | O_BINARY | _O_CREAT ) ) == -1 ) //rm52k_r1
#else
		if ( ( p_ref = fopen ( input->reffile, "rb" ) ) == 0 )
#endif

		{
			fprintf ( stdout, " Input Texture Reference File		: %s does not exist \n", input->reffile );
			fprintf ( stdout, "                                          SNR values are not available\n" );
			RefPicExist = 0;  // 20071224
		}
		else
		{
			fprintf ( stdout, " Input Texture Reference		: %s \n", input->reffile[i] );
			RefPicExist = 1;  // 20071224
		}




		if ( input->output_dec_pic ) //output_dec_pic
		{
			if ( ( p_depth_multiView_out[i] = _open ( input->depth_outfile[i], _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE ) ) == -1 )

			{
				snprintf ( errortext, ET_SIZE, "Error open file %s ", input->outfile );
				error ( errortext, 500 );
			}
		}


		if ( ( p_depth_multiView_ref[i] = _open ( input->depth_reffile[i], O_RDWR | O_BINARY | _O_CREAT ) ) == -1 ) //rm52k_r1


		{
			fprintf ( stdout, " Input Depth Reference File		: %s does not exist \n", input->reffile );
			fprintf ( stdout, "                                          SNR values are not available\n" );
			RefPicExist = 0;  // 20071224
		}
		else
		{
			fprintf ( stdout, " Input Depth Reference File		: %s \n", input->reffile[i] );
			RefPicExist = 1;  // 20071224
		}

	}
}


#endif



/*
*************************************************************************
* Function:main function for decoder
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/
void InitZigzagScan ( int **scan, unsigned int uiBitSize )
{
  int i, j, pos;
  scan[0][0] = 0;
  scan[0][1] = 0;
  pos = 0;

  for ( i = 1; i < ( ( 1 << ( uiBitSize + 1 ) ) - 1 ); i++ )
  {
    if ( i < ( 1 << uiBitSize ) )
    {
      if ( i % 2 == 1 )
      {
        pos++;
        scan[pos][0] = scan[pos - 1][0] + 1;
        scan[pos][1] = scan[pos - 1][1];

        for ( j = 1; j < min ( i + 1, ( ( 1 << ( uiBitSize + 1 ) ) - i - 1 ) ); j++ )
        {
          pos++;
          scan[pos][0] = scan[pos - 1][0] - 1;
          scan[pos][1] = scan[pos - 1][1] + 1;
        }
      }
      else
      {
        pos++;
        scan[pos][0] = scan[pos - 1][0];
        scan[pos][1] = scan[pos - 1][1] + 1;

        for ( j = 1; j < min ( i + 1, ( ( 1 << ( uiBitSize + 1 ) ) - i - 1 ) ); j++ )
        {
          pos++;
          scan[pos][0] = scan[pos - 1][0] + 1;
          scan[pos][1] = scan[pos - 1][1] - 1;
        }
      }
    }
    else
    {
      if ( i % 2 == 1 )
      {
        pos++;
        scan[pos][0] = scan[pos - 1][0];
        scan[pos][1] = scan[pos - 1][1] + 1;

        for ( j = 1; j < min ( i + 1, ( ( 1 << ( uiBitSize + 1 ) ) - i - 1 ) ); j++ )
        {
          pos++;
          scan[pos][0] = scan[pos - 1][0] - 1;
          scan[pos][1] = scan[pos - 1][1] + 1;
        }
      }
      else
      {
        pos++;
        scan[pos][0] = scan[pos - 1][0] + 1;
        scan[pos][1] = scan[pos - 1][1];

        for ( j = 1; j < min ( i + 1, ( ( 1 << ( uiBitSize + 1 ) ) - i - 1 ) ); j++ )
        {
          pos++;
          scan[pos][0] = scan[pos - 1][0] + 1;
          scan[pos][1] = scan[pos - 1][1] - 1;
        }
      }
    }
  }
}

void InitZigzagScan_NSQT (int **scan, int iWidth, int iHeight)
{
  int x, y, c = 0;

  // starting point
  scan[c][0] = 0;
  scan[c][1] = 0;
  c++;

  // loop
  x=1; y=0;
  while (1)
  {
    // decrease loop
    while ( x>=0 )
    {
      if ( x >= 0 && x < iWidth && y >= 0 && y < iHeight )
      {
        scan[c][0] = x;
        scan[c][1] = y;
        c++;
      }
      x--; y++;
    }
    x=0;

    // increase loop
    while ( y>=0 )
    {
      if ( x >= 0 && x < iWidth && y >= 0 && y < iHeight )
      {
        scan[c][0] = x;
        scan[c][1] = y;
        c++;
      }
      x++; y--;
    }
    y=0;

    // termination condition
    if ( c >= iWidth*iHeight ) break;
  }
}

void  InitCGZigzagScan( int **scan, int iWidth, int iHeight )
{

  int *** AVS_SCAN_4x4;
  int *** AVS_SCAN_CG;
  int i, j, k;
  
  get_mem3Dint ( &AVS_SCAN_4x4, 2, 16, 2 );
  get_mem3Dint ( &AVS_SCAN_CG, 2, iWidth*iHeight/16, 2 );
  InitZigzagScan ( AVS_SCAN_4x4[1],  2 );
  InitZigzagScan_NSQT ( AVS_SCAN_CG[1], iWidth/4, iHeight/4 );

  scan[0][0] = 0;
  scan[0][1] = 0;
  
  for ( i = 1; i < iWidth * iHeight ; i++) 
  {
    j = i / 16;
    k = i % 16;

    scan[i][0] = AVS_SCAN_CG[1][j][0]*4 + AVS_SCAN_4x4[1][k][0];
    scan[i][1] = AVS_SCAN_CG[1][j][1]*4 + AVS_SCAN_4x4[1][k][1];
  }  
 free_mem3Dint ( AVS_SCAN_4x4, 2);
 free_mem3Dint ( AVS_SCAN_CG, 2);
}

int main ( int argc, char **argv )
{
#if REF_OUTPUT
	int i,j;
#endif
#if SIMP_INTRA
  int k,c;
#endif
  // allocate memory for the structures
  if ( ( input = ( struct inp_par * ) calloc ( 1, sizeof ( struct inp_par ) ) ) == NULL )
  {
    no_mem_exit ( "main: input" );
  }

#if MULTIVIEW_CODING
  snr = &multiView_snrs[0];
#else
  if ( ( snr = ( SNRParameters * ) calloc ( 1, sizeof ( SNRParameters ) ) ) == NULL )
  {
	  no_mem_exit ( "main: snr" );
  }
#endif

  if ( ( img = ( ImageParameters * ) calloc ( 1, sizeof ( ImageParameters ) ) ) == NULL )
  {
    no_mem_exit ( "main: img" );
  }

#if MULTIVIEW_CODING
  StatBitsPtr = &multiView_StatBits[0];
#else
  if ( ( StatBitsPtr = ( struct StatBits * ) calloc ( 1, sizeof ( struct StatBits ) ) ) == NULL )
  {
	  no_mem_exit ( "main: StatBits" );
  }
#endif

  img->seq_header_indicate = 0;
  img->B_discard_flag = 0;
  StatBitsPtr->curr_frame_bits = StatBitsPtr->prev_frame_bits
                                 = StatBitsPtr->emulate_bits = StatBitsPtr->last_unit_bits = 0; //rm52k_r2
  StatBitsPtr->bitrate = StatBitsPtr->coded_pic_num = StatBitsPtr->time_s = 0; //rm52k_r2

  currStream = AllocBitstream();

  eos = 0;

  init_conf ( argc, argv );

  OpenBitstreamFile ( input->infile );

  if ( input->ref_pic_order )   //ref order
  {
    dec_ref_num = 0;
  }

  malloc_slice ();
  get_mem3Dint ( &AVS_SCAN8x8, 2, 64, 2 );
  get_mem3Dint ( &AVS_SCAN16x16, 2, 256, 2 );
  get_mem3Dint ( &AVS_SCAN32x32, 2, 1024, 2 );
  InitZigzagScan ( AVS_SCAN8x8[1], 3 );
  InitZigzagScan ( AVS_SCAN16x16[1], 4 );
  InitZigzagScan ( AVS_SCAN32x32[1], 5 );
  get_mem3Dint ( &AVS_SCAN4x4, 2, 16, 2 );
  InitZigzagScan ( AVS_SCAN4x4[1], 2 );
  get_mem3Dint ( &AVS_CG_SCAN8x8, 2, 64, 2 );
  get_mem3Dint ( &AVS_CG_SCAN16x16, 2, 256, 2 );
  get_mem3Dint ( &AVS_CG_SCAN32x32, 2, 1024, 2 );
  get_mem3Dint( &AVS_SCAN4x16, 2, 64, 2);
  get_mem3Dint( &AVS_SCAN16x4, 2, 64, 2);
  get_mem3Dint( &AVS_SCAN2x8, 2, 16, 2);
  get_mem3Dint( &AVS_SCAN8x2, 2, 16, 2);
  get_mem3Dint( &AVS_SCAN32x8, 2, 256, 2);
  get_mem3Dint( &AVS_SCAN8x32, 2, 256, 2);
  InitCGZigzagScan( AVS_SCAN4x16[1], 16, 4);
  InitCGZigzagScan( AVS_SCAN16x4[1], 4, 16);
  InitCGZigzagScan( AVS_SCAN32x8[1], 8, 32);
  InitCGZigzagScan( AVS_SCAN8x32[1], 32, 8);

  InitCGZigzagScan ( AVS_CG_SCAN8x8[1], 8, 8 );
  InitCGZigzagScan ( AVS_CG_SCAN16x16[1], 16, 16 );
  InitCGZigzagScan ( AVS_CG_SCAN32x32[1], 32, 32 );

  InitZigzagScan_NSQT(AVS_SCAN2x8[1], 8, 2);
  InitZigzagScan_NSQT(AVS_SCAN8x2[1], 2, 8);

#if SIMP_INTRA
  memset(g_log2size, -1, MAX_CU_SIZE+1 );
  c=2;
  for ( k=4; k<=MAX_CU_SIZE; k*=2 )
  {
    g_log2size[ k ] = c;
    c++;
  }
#endif

#if MULTIVIEW_CODING
  {
	  int viewNum, refNum;
	  for (viewNum=0; viewNum<input->view_number; viewNum++)
	  {
#if 1
		  for (refNum=0; refNum<REF_MAXBUFFER; refNum++)
		  {
			  img->multiView_imgcoi_ref[viewNum][refNum] = -257;
			  img->multiView_imgtr_fwRefDistance[viewNum][refNum] = -256;
			  memset(multiView_ref_poc[viewNum][refNum], 0, sizeof(int)*4);
			  memset(multiView_depth_ref_poc[viewNum][refNum], 0, sizeof(int)*4);
			  img->multiView_depth_imgcoi_ref[viewNum][refNum] = -257;
			  img->multiView_depth_imgtr_fwRefDistance[viewNum][refNum] = -256;
		  }
#else
		  memset(img->multiView_imgcoi_ref[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_imgtr_fwRefDistance[viewNum], 0, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_depth_imgcoi_ref[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_depth_imgtr_fwRefDistance[viewNum], 0, sizeof(int)*REF_MAXBUFFER);
#endif
		  multiView_depth_last_output[viewNum] = -1;
		  multiView_last_output[viewNum] = -1;


		  memset(img->multiView_refered_by_others[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_depth_refered_by_others[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_is_output[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
		  memset(img->multiView_depth_is_ouput[viewNum], -1, sizeof(int)*REF_MAXBUFFER);
	  }
  }
  for( i = 0 ; i < MAX_VIEW; i ++)
  {
	  outprint.buffer_num[i] = 0;
  }
#else
  outprint.buffer_num=0;
#endif

  last_output = -1;
  end_SeqTr = -1;
  curr_IDRtr = 0;
  curr_IDRcoi = 0;
  next_IDRtr = 0;
  next_IDRcoi = 0;
  // Allocate Slice data struct
  img->number = 0;
  img->type = I_IMG;

  {
	  int i;
	  for ( i = 0; i < REF_MAXBUFFER; i++)
	  {
#if REF_MINUS
		  img->imgcoi_ref[i] = -257;
		  img->imgtr_fwRefDistance[i] = -256;
#else
		  img->imgcoi_ref[i] = -1;
		  img->imgtr_fwRefDistance[i] = 0;
#endif
#if M3481_REMOVE_BUGFIX
		  img->is_output[i] = -1;
#endif
	  }
  }
  img->imgtr_next_P = 0;
#if !MULTIVIEW_CODING
  img->imgcoi_next_ref = 0;
#endif


#if WEIGHTED_SKIP
  img->num_of_references = 0;
#endif
  seq_header = 0;

  img->new_sequence_flag   = 1;

  vec_flag = 0;

  FrameNum = 0;

  // B pictures
  Bframe_ctr = 0;
#if REF_MINUS
  total_frames = 0;
#endif

  // time for total decoding session
  tot_time = 0;

  do
  {
#if MULTIVIEW_CODING
	  while ( ( multiView_decode_one_frame( snr ) != EOS ) && ( !IsEndOfBitstream() ) );
#else
	  while ( ( decode_one_frame ( snr ) != EOS ) && ( !IsEndOfBitstream() ) );
#endif
  }
  while ( !IsEndOfBitstream() );
#if ALF
  if (input->alf_enable)
  {
	  ReleaseAlfGlobalBuffer();
  } 
#endif
  if ( StatBitsPtr->time_s == 0 )
  {
    StatBitsPtr->total_bitrate[StatBitsPtr->time_s++] = StatBitsPtr->bitrate;
  }

  eos = 1;
#if MULTIVIEW_CODING
#if REF_OUTPUT

  // output the delayed picture in random access condition
  for( k = 0; k < input->view_number; k ++)
  {
	  for (j=0; j<outprint.buffer_num[k]; j++)
	  {
		  int tmp_min,pos=-1;
		  tmp_min = 1<<20;

		  for ( i=0; i<outprint.buffer_num[k]; i++)
		  {
			  if (outprint.stdoutdata[k][i].tr<tmp_min && outprint.stdoutdata[k][i].tr>multiView_last_output[k])
			  {
				  pos=i;
				  tmp_min=outprint.stdoutdata[k][i].tr;
			  }
		  }
		  for (i=0; i<REF_MAXBUFFER; i++)
		  {
			  ref[i]					  = multiView_ref[k][i];
			  img->imgtr_fwRefDistance[i] = img->multiView_imgtr_fwRefDistance[k][i];
			  img->imgcoi_ref[i]		  = img->multiView_imgcoi_ref[k][i]; 
		  }
		  if (pos!=-1)
		  {
			  multiView_last_output[k] = outprint.stdoutdata[k][pos].tr;
			  report_frame( outprint, pos );
			  write_frame( p_multiView_out[k], outprint.stdoutdata[k][pos].tr );

		  }
	  }
	  if(input->bUseDepth == 1)
	  {
		  for (j=0; j<outprint.depth_buffer_num[k]; j++)
		  {
			  int tmp_min,pos=-1;
			  tmp_min = 1<<20;

			  for ( i=0; i<outprint.depth_buffer_num[k]; i++)
			  {
				  if (outprint.depth_stdoutdata[k][i].tr<tmp_min && outprint.depth_stdoutdata[k][i].tr>multiView_depth_last_output[k])
				  {
					  pos=i;
					  tmp_min=outprint.depth_stdoutdata[k][i].tr;
				  }
			  }
			  for (i=0; i<REF_MAXBUFFER; i++)
			  {
				  ref[i]					  = multiView_depth_ref[k][i];
				  img->imgtr_fwRefDistance[i] = img->multiView_depth_imgtr_fwRefDistance[k][i];
				  img->imgcoi_ref[i]		  = img->multiView_depth_imgcoi_ref[k][i]; 
			  }
			  if (pos!=-1)
			  {
				  multiView_depth_last_output[k] = outprint.depth_stdoutdata[k][pos].tr;
				  report_frame( outprint, pos );
				  write_frame( p_depth_multiView_out[k], outprint.depth_stdoutdata[k][pos].tr );

			  }
		  }
	  }
  }
#endif 
#else
#if REF_OUTPUT
  for (j=0; j<outprint.buffer_num; j++)
  {
	  int tmp_min,pos=-1;
	  tmp_min = 1<<20;

	  for ( i=0; i<outprint.buffer_num; i++)
	  {
		  if (outprint.stdoutdata[i].tr<tmp_min && outprint.stdoutdata[i].tr>last_output)
		  {
			  pos=i;
			  tmp_min=outprint.stdoutdata[i].tr;
		  }
	  }
	  if (pos!=-1)
	  {
		  last_output = outprint.stdoutdata[pos].tr;
		  report_frame( outprint, pos );
		  write_frame( p_out, outprint.stdoutdata[pos].tr );

	  }
  }
#endif 
#endif

#if MULTIVIEW_CODING
  multiView_report();
#else
  report ( snr );
#endif

  free_mem3Dint ( AVS_SCAN8x8, 2 );
  free_mem3Dint ( AVS_SCAN16x16, 2 );
  free_mem3Dint ( AVS_SCAN32x32, 2 );
  free_mem3Dint ( AVS_SCAN4x4, 2 );
  free_mem3Dint ( AVS_CG_SCAN8x8, 2 );
  free_mem3Dint ( AVS_CG_SCAN16x16, 2 );
  free_mem3Dint ( AVS_CG_SCAN32x32, 2 );
  FreeBitstream();
  free_slice ();
  free_global_buffers ();

#if MULTIVIEW_CODING
  Free_MultiView_Buffers();
#endif

  CloseBitstreamFile();

#if ROI_M3264
  ClosePosFile();	
#endif

#ifdef WIN32
#if MULTIVIEW_CODING
  for ( i = 0; i < input -> view_number; i ++)
  {
	  _close ( p_multiView_out[i] );

	  if ( p_multiView_ref[i] )
	  {
		  _close ( p_multiView_ref[i] );
	  }
#if MULTIVIEW_CODING
	  if (input->bUseDepth)
	  {
		  _close ( p_depth_multiView_out[i] );

		  if ( p_depth_multiView_ref[i] )
		  {
			  _close ( p_depth_multiView_ref[i] );
		  }
	  }
#else
	  _close ( p_depth_multiView_out[i] );

	  if ( p_depth_multiView_ref[i] )
	  {
		  _close ( p_depth_multiView_ref[i] );
	  }
#endif
  }
#else
  _close ( p_out );

  if ( p_ref )
  {
    _close ( p_ref );
  }
#endif

#ifdef AVS2_S2_BGLONGTERM
  _close( p_out_background );
  if ( p_ref_background )
  {
	  _close ( p_ref_background );
  }
#endif

#else
#if MULTIVIEW_CODING
  for ( i = 0; i < input -> view_number; i ++)
  {
	  fclose ( p_multiView_out[i] );

	  if ( p_multiView_ref[i] )
	  {
		  fclose ( p_multiView_ref[i] );
	  }
#if MULTIVIEW_CODING
	  if (input->bUseDepth)
	  {
		  fclose ( p_depth_multiView_out[i] );

		  if ( p_depth_multiView_ref[i] )
		  {
			  fclose ( p_depth_multiView_ref[i] );
		  }
	  }
#else
	  fclose ( p_depth_multiView_out[i] );

	  if ( p_depth_multiView_ref[i] )
	  {
		  fclose ( p_depth_multiView_ref[i] );
	  }
#endif

  }
#else
  fclose ( p_out );

  if ( p_ref )
  {
    fclose ( p_ref );
  }
#endif
#ifdef AVS2_S2_BGLONGTERM
  if ( p_out_background )
  {
    fclose( p_out_background );
  }
  if ( p_ref_background )
  {
	  fclose ( p_ref_background );
  }
#endif
#endif

#if TRACE
  fclose ( p_trace );
#endif

#if FIX_LEAK
  free_mem3Dint (AVS_SCAN4x16, 2);
  free_mem3Dint (AVS_SCAN16x4, 2);
  free_mem3Dint (AVS_SCAN2x8, 2);
  free_mem3Dint (AVS_SCAN8x2, 2);
  free_mem3Dint (AVS_SCAN32x8,2);
  free_mem3Dint (AVS_SCAN8x32, 2);
#endif

  free ( input );
#if !MULTIVIEW_CODING
  free ( snr );
  free ( StatBitsPtr );//1105
#endif
  free ( img );
  printf("\n=============== Check value bound ==============================\n");
  printf("value_s_bound: %d\n",NUN_VALUE_BOUND);
  printf("max_value_s: %d\n",max_value_s);
  printf("================================================================\n");
  return 0;
}

/*
*************************************************************************
* Function:Initilize some arrays
* Input:
* Output:
* Return:
* Attention:
*************************************************************************
*/


void init () //!< image parameters
{
  int i;

  // initilize quad mat`rix used in snr routine
#if EXTEND_BD
	for ( i = 0; i <  (1 << input->sample_bit_depth); i++ )
#else
	for ( i = 0; i <  256; i++ )
#endif
  {
    img->quad[i] = i * i;
  }

}

/*
*************************************************************************
* Function:Read input from configuration file
* Input:Name of configuration filename
* Output:
* Return:
* Attention:
*************************************************************************
*/

void init_conf ( int numpar, char **config_str )
{
  FILE *fd;

#if MULTIVIEW_CODING      
  char		*TempSplit;  
  char		Temp[1000],Temp1[1000];  //
  int		count;  // count numbers
  int		i=0;
#endif

#if MULTIVIEW_CODING
  int		maxViewNum = 0;
  char		viewOutput[1000];
  char		depthOutput[1000];
  char		viewRef[1000];
  char		depthRef[1000];
#endif

  input->check_BBV_flag = 0;

  // read the decoder configuration file
#if MULTIVIEW_CODING
  if ( numpar != 1 && numpar != 2 && numpar != 8 && numpar != 11)
#else
  if ( numpar != 1 && numpar != 2 && numpar != 8 )
#endif
  {
    snprintf ( errortext, ET_SIZE,
               "Usage: %s <config.dat> <avsfilename> <decfilename> <reffilename> <ref_num> <lfdisable> <yuv_structure> <bbv_check>\n \
      ?-the decoder can be configured by configfile or by command line \n \
      ?-param with only <config.dat> defines decoder with file\n \
      ?-params with allof the params define decoder params with command line\n \
      ", config_str[0] );
    error ( errortext, 300 );
  }

  if ( numpar == 1 )
  {
    fprintf ( stdout, "**************************************************************************\n" );
    fprintf ( stdout, "The decoder config file doesn't exist. Use the default parameters instead!\n" );
    fprintf ( stdout, "**************************************************************************\n\n" );
  }

  if ( numpar != 1 )
  {
    if ( ( fd = fopen ( config_str[1], "r" ) ) == NULL )
    {
      snprintf ( errortext, ET_SIZE, "Error: Control file %s not found\n", config_str[1] );
      error ( errortext, 300 );
    }
  }

  strcpy ( input->infile, "test.avs" );

#if MULTIVIEW_CODING
  input->view_number = 1;
#else
  strcpy ( input->outfile, "test_dec.yuv" );
  strcpy ( input->reffile, "test_rec.yuv" );
#endif
#if ROI_M3264
  strcpy ( input->out_datafile, "out_position_data.txt");
#endif
  input->buf_cycle = 2;
  input->LFParametersFlag = 0;
  input->yuv_structure = 0;
  input->check_BBV_flag = 0;
  input->ref_pic_order  = 0;
  input->output_dec_pic = 1;

  if ( numpar == 2 )
  {
    fscanf ( fd, "%s", input->infile );           // AVS compressed input bitsream
    fscanf ( fd, "%*[^\n]" );

#if MULTIVIEW_CODING
	fscanf(fd,"%s",viewOutput);
	fscanf(fd, "%*[^\n]" );
	fscanf(fd,"%s",viewRef);
	fscanf(fd, "%*[^\n]" );
	fscanf(fd,"%s",depthOutput);
	fscanf(fd, "%*[^\n]" );
	fscanf(fd,"%s",depthRef);
	fscanf(fd, "%*[^\n]" );
#else
	fscanf ( fd, "%s", input->outfile );          // YUV output format
	fscanf ( fd, "%*[^\n]" );

	fscanf ( fd, "%s", input->reffile );          // reference file
	fscanf ( fd, "%*[^\n]" );
#endif
    fscanf ( fd, "%d,", &input->yuv_structure );
    fscanf ( fd, "%*[^\n]" );

    fscanf ( fd, "%d,", &input->ref_pic_order );
    fscanf ( fd, "%*[^\n]" );

    fscanf ( fd, "%d,", &input->output_dec_pic );
    fscanf ( fd, "%*[^\n]" );

#if MULTIVIEW_CODING
	fscanf ( fd, "%d,", &input->view_number );
	fscanf ( fd, "%*[^\n]" );

	for (i=0; i<input->view_number; i++)
	{
		initFileNames(input->outfile[i], viewOutput, i);
		initFileNames(input->reffile[i], viewRef, i);
		initFileNames(input->depth_outfile[i], depthOutput, i);
		initFileNames(input->depth_reffile[i], depthRef, i);
	}
#endif
  }

  if ( numpar == 8 ) //The decoder will be configured with the command line in the case of 9 parameters input
  {

    strcpy ( input->infile, config_str[2] );
#if MULTIVIEW_CODING
	strcpy ( input->outfile[0], config_str[3] );
	strcpy ( input->reffile[0], config_str[4] );
#else
	strcpy ( input->outfile, config_str[3] );
	strcpy ( input->reffile, config_str[4] );
#endif

    input->yuv_structure = atoi ( config_str[5] );
    input->ref_pic_order  = atoi ( config_str[6] );
    input->output_dec_pic  = atoi ( config_str[7] );
  }

#if MULTIVIEW_CODING
  else if (numpar == 11)
  {
	  strcpy ( input->infile, config_str[2] );

	  strcpy ( viewOutput, config_str[3] );
	  strcpy ( viewRef, config_str[4] );
	  strcpy (depthOutput, config_str[5]);
	  strcpy (depthRef, config_str[6]);

	  input->yuv_structure = atoi ( config_str[7] );
	  input->ref_pic_order  = atoi ( config_str[8] );
	  input->output_dec_pic  = atoi ( config_str[9] );
	  input->view_number = atoi(config_str[10]);

	  for (i=0; i<input->view_number; i++)
	  {
		  initFileNames(input->outfile[i], viewOutput, i);
		  initFileNames(input->reffile[i], viewRef, i);
		  initFileNames(input->depth_outfile[i], depthOutput, i);
		  initFileNames(input->depth_reffile[i], depthRef, i);
	  }
  }
#endif


#if TRACE

  if ( ( p_trace = fopen ( TRACEFILE, "w" ) ) == 0 ) // append new statistic at the end
  {
    snprintf ( errortext, ET_SIZE, "Error open file %s!", TRACEFILE );
    error ( errortext, 500 );
  }

#endif

#ifdef WIN32

  if ( input->output_dec_pic ) //output_dec_pic
  {
#if !MULTIVIEW_CODING
    if ( ( p_out = _open ( input->outfile, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE ) ) == -1 )
#endif
#else
  if ( input->output_dec_pic ) //output_dec_pic
  {
    if ( ( p_out = fopen ( input->outfile, "wb" ) ) == 0 )
#endif
#if !MULTIVIEW_CODING
	{
		snprintf ( errortext, ET_SIZE, "Error open file %s ", input->outfile );
		error ( errortext, 500 );
	}
#endif
#if AVS2_SCENE_CD
#else
#ifdef AVS2_S2_BGLONGTERM
#ifdef WIN32
	if ( ( p_out_background = _open ( "background_dec.yuv", _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE ) ) == -1 )
#else
	if ( ( p_out_background = fopen ( "background_dec.yuv", "wb" ) )  == 0 )
#endif
	{
		snprintf ( errortext, ET_SIZE, "Error open file background_out.yuv " );
		error ( errortext, 500 );
	}
#endif
#endif
  }

  fprintf ( stdout, "--------------------------------------------------------------------------\n" );
  //  fprintf(stdout," Decoder config file                    : %s \n",config_filename);  // 20071224
  fprintf ( stdout, " Decoder config file                    : %s \n", config_str[0] );
  fprintf ( stdout, "--------------------------------------------------------------------------\n" );
  fprintf ( stdout, " Input AVS bitstream                    : %s \n", input->infile );
#if MULTIVIEW_CODING
  fprintf ( stdout, " Output decoded YUV 4:2:0               : %s \n", input->outfile[0] );
#else
  fprintf ( stdout, " Output decoded YUV 4:2:0               : %s \n", input->outfile );
#endif
  fprintf ( stdout, " Output status file                     : %s \n", LOGFILE );
#if EXTEND_BD
	fprintf ( stdout, " Output file bit depth                  : %d \n", input->output_bit_depth );
#endif

#ifdef WIN32
#if !MULTIVIEW_CODING
  if ( ( p_ref = _open ( input->reffile, O_RDWR | O_BINARY | _O_CREAT ) ) == -1 ) //rm52k_r1
#endif
#else
  if ( ( p_ref = fopen ( input->reffile, "rb" ) ) == 0 )
#endif
#if !MULTIVIEW_CODING
  {
	  fprintf ( stdout, " Input reference file                   : %s does not exist \n", input->reffile );
	  fprintf ( stdout, "                                          SNR values are not available\n" );
	  RefPicExist = 0;  // 20071224
  }
  else
  {
	  fprintf ( stdout, " Input reference file                   : %s \n", input->reffile );
	  RefPicExist = 1;  // 20071224
  }
#endif
#if AVS2_SCENE_CD
#else
#ifdef AVS2_S2_BGLONGTERM
  if(input->profile_id == 0x50){
#ifdef WIN32
	if( (p_ref_background = _open ( "background_ref.yuv", O_RDWR | O_BINARY ) ) == -1)
#else
	if( (p_ref_background = fopen ( "background_ref.yuv", "rb" ) ) == 0)
#endif
	  {
		  snprintf ( errortext, ET_SIZE, "Error open file background_ref.yuv " );
		  error ( errortext, 500 );
	  }
  }
#endif
#endif

#if MULTIVIEW_CODING
  multiView_openfile ();
#endif

  fprintf ( stdout, "--------------------------------------------------------------------------\n" );
  fprintf ( stdout, " Frame   TR    QP   SnrY    SnrU    SnrV   Time(ms)   FRM/FLD  Bits  EmulateBits\n" );
}

/*
*************************************************************************
* Function:Reports the gathered information to appropriate outputs
* Input:
struct inp_par *input,
ImageParameters *img,
SNRParameters *stat
* Output:
* Return:
* Attention:
*************************************************************************
*/

void report ( SNRParameters *snr )
{
#define OUTSTRING_SIZE 255
  char string[OUTSTRING_SIZE];
  FILE *p_log;

#ifndef WIN32
  time_t  now;
  struct tm *l_time;
#else
  char timebuf[128];
#endif

  if ( img->sequence_end_flag )
  {
	  fprintf ( stdout, "Sequence End\n\n" );
  }
  {
	  int i;
	  float framerate[8] = {24000 / 1001, 24, 25, 30000 / 1001, 30, 50, 60000 / 1001, 60};

	  if ( ( int ) ( StatBitsPtr->coded_pic_num - ( StatBitsPtr->time_s + 1 ) *framerate[frame_rate_code - 1] + 0.5 ) == 0 )
	  {
		  StatBitsPtr->total_bitrate[StatBitsPtr->time_s++] = StatBitsPtr->bitrate;
		  StatBitsPtr->bitrate = 0;
	  }

	  StatBitsPtr->total_bitrate[StatBitsPtr->time_s - 1] += 32;
	  printf ( "Second(s)\tBitrate(bit/s)\n" );

	  for ( i = 0; i < StatBitsPtr->time_s; i++ )
	  {
		  printf ( " %3d\t\t %d\n", i, StatBitsPtr->total_bitrate[i] );
	  }

	  if ( StatBitsPtr->time_s == 0 )
	  {
		  printf ( " %3d\t\t %d\n", 0, StatBitsPtr->total_bitrate[0] );
	  }
  }

  fprintf ( stdout, "-------------------- Average SNR all frames ------------------------------\n" );
  fprintf ( stdout, " SNR Y(dB)           : %5.2f\n", snr->snr_ya );
  fprintf ( stdout, " SNR U(dB)           : %5.2f\n", snr->snr_ua );
  fprintf ( stdout, " SNR V(dB)           : %5.2f\n", snr->snr_va );
  fprintf ( stdout, " Total decoding time : %.3f sec \n", tot_time * 0.001 );
  fprintf ( stdout, "--------------------------------------------------------------------------\n" );

  fprintf ( stdout, " Exit RD %s decoder, ver %s ", RD, VERSION );
  fprintf ( stdout, "\n" );

  snprintf ( string, OUTSTRING_SIZE, "%s", LOGFILE );

  if ( ( p_log = fopen ( string, "r" ) ) == 0 )        // check if file exist
  {
    if ( ( p_log = fopen ( string, "a" ) ) == 0 )
    {
      snprintf ( errortext, ET_SIZE, "Error open file %s for appending", string );
      error ( errortext, 500 );
    }
    else                                              // Create header to new file
    {
      fprintf ( p_log, " ------------------------------------------------------------------------------------------\n" );
      fprintf ( p_log, "|  Decoder statistics. This file is made first time, later runs are appended               |\n" );
      fprintf ( p_log, " ------------------------------------------------------------------------------------------ \n" );
      fprintf ( p_log, "| Date  | Time  |    Sequence        |#Img|Format|SNRY 1|SNRU 1|SNRV 1|SNRY N|SNRU N|SNRV N|\n" );
      fprintf ( p_log, " ------------------------------------------------------------------------------------------\n" );
    }
  }
  else
  {
    fclose ( p_log );
    p_log = fopen ( string, "a" );              // File exist,just open for appending
  }

#ifdef WIN32
  _strdate ( timebuf );
  fprintf ( p_log, "| %1.5s |", timebuf );

  _strtime ( timebuf );
  fprintf ( p_log, " % 1.5s |", timebuf );
#else
  now = time ( ( time_t * ) NULL ); // Get the system time and put it into 'now' as 'calender time'
  time ( &now );
  l_time = localtime ( &now );
  strftime ( string, sizeof string, "%d-%b-%Y", l_time );
  fprintf ( p_log, "| %1.5s |", string );

  strftime ( string, sizeof string, "%H:%M:%S", l_time );
  fprintf ( p_log, "| %1.5s |", string );
#endif

  fprintf ( p_log, "%20.20s|", input->infile );

  fprintf ( p_log, "%3d |", img->number );

  fprintf ( p_log, "%6.3f|", snr->snr_y1 );
  fprintf ( p_log, "%6.3f|", snr->snr_u1 );
  fprintf ( p_log, "%6.3f|", snr->snr_v1 );
  fprintf ( p_log, "%6.3f|", snr->snr_ya );
  fprintf ( p_log, "%6.3f|", snr->snr_ua );
  fprintf ( p_log, "%6.3f|\n", snr->snr_va );

  fclose ( p_log );

  snprintf ( string, OUTSTRING_SIZE, "%s", DATADECFILE );
  p_log = fopen ( string, "a" );

  if ( Bframe_ctr != 0 ) // B picture used
  {
    fprintf ( p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5d "
              "%2.2f %2.2f %2.2f %5d "
              "%2.2f %2.2f %2.2f %5d %.3f\n",
              img->number, 0, img->qp,
              snr->snr_y1,
              snr->snr_u1,
              snr->snr_v1,
              0,
              0.0,
              0.0,
              0.0,
              0,
              snr->snr_ya,
              snr->snr_ua,
              snr->snr_va,
              0,
              ( double ) 0.001 * tot_time / ( img->number + Bframe_ctr - 1 ) );
  }
  else
  {
    fprintf ( p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5d "
              "%2.2f %2.2f %2.2f %5d "
              "%2.2f %2.2f %2.2f %5d %.3f\n",
              img->number, 0, img->qp,
              snr->snr_y1,
              snr->snr_u1,
              snr->snr_v1,
              0,
              0.0,
              0.0,
              0.0,
              0,
              snr->snr_ya,
              snr->snr_ua,
              snr->snr_va,
              0,
              ( double ) 0.001 * tot_time / img->number );
  }

  fclose ( p_log );
}

/*
*************************************************************************
* Function:Allocates a Bitstream
* Input:
* Output:allocated Bitstream point
* Return:
* Attention:
*************************************************************************
*/

Bitstream *AllocBitstream()
{
  Bitstream *bitstream;

  bitstream = ( Bitstream * ) calloc ( 1, sizeof ( Bitstream ) );

  if ( bitstream == NULL )
  {
    snprintf ( errortext, ET_SIZE, "AllocBitstream: Memory allocation for Bitstream failed" );
    error ( errortext, 100 );
  }

  bitstream->streamBuffer = ( unsigned char * ) calloc ( MAX_CODED_FRAME_SIZE, sizeof ( unsigned char ) );

  if ( bitstream->streamBuffer == NULL )
  {
    snprintf ( errortext, ET_SIZE, "AllocBitstream: Memory allocation for streamBuffer failed" );
    error ( errortext, 100 );
  }

  return bitstream;
}


/*
*************************************************************************
* Function:Frees a partition structure (array).
* Input:Partition to be freed, size of partition Array (Number of Partitions)
* Output:
* Return:
* Attention:n must be the same as for the corresponding call of AllocPartition
*************************************************************************
*/

void FreeBitstream ()
{
  assert ( currStream != NULL );
  assert ( currStream->streamBuffer != NULL );

  free ( currStream->streamBuffer );
  free ( currStream );
}

/*
*************************************************************************
* Function:Dynamic memory allocation of frame size related global buffers
buffers are defined in global.h, allocated memory must be freed in
void free_global_buffers()
* Input:Input Parameters struct inp_par *input, Image Parameters ImageParameters *img
* Output:Number of allocated bytes
* Return:
* Attention:
*************************************************************************
*/


int init_global_buffers ()
{
  int i, j;
  int refnum;

  int memory_size = 0;
  int img_height = ( vertical_size + img->auto_crop_bottom );

  img->buf_cycle = input->buf_cycle + 1;

  img->buf_cycle *= 2;

#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if(background_picture_enable){
#ifdef WIN32
	if( (p_ref_background = _open ( "background_ref.yuv", O_RDWR | O_BINARY ) ) == -1)
#else
	if( (p_ref_background = fopen ( "background_ref.yuv", "rb" ) ) == 0)
#endif
	  {
		  snprintf ( errortext, ET_SIZE, "Error open file background_ref.yuv " );
		  error ( errortext, 500 );
	  }
#ifdef WIN32
	if ( input->output_dec_pic && ( p_out_background = _open ( "background_dec.yuv", _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE ) ) == -1 )
#else
	if ( input->output_dec_pic && ( p_out_background = fopen ( "background_dec.yuv", "wb" ) )  == 0 )
#endif
	{
		snprintf ( errortext, ET_SIZE, "Error open file background_out.yuv " );
		error ( errortext, 500 );
	}
  }
#endif

#if AVS2_SCENE_CD
  if(background_picture_enable)
#else
  if(background_picture_enable && input->profile_id == 0x50)
#endif
  {
	  for(i=0;i<3;i++)
	  {
		  if(i==0)
			  get_mem2D(&background_frame[i],img->height,img->width);
		  else
			  get_mem2D(&background_frame[i],img->height_cr,img->width_cr);
	  }
  }
#endif

#if !MULTIVIEW_CODING
  // allocate memory for imgYPrev
  memory_size += get_mem2D ( &imgYPrev, img_height, img->width );
  memory_size += get_mem3D ( &imgUVPrev, 2, img_height / ( input->chroma_format == 1 ? 2 : 1 ), img->width_cr );

  // allocate memory for reference frames of each block: refFrArr
  memory_size += get_mem2Dint ( &refFrArr, img_height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
#endif

#if MH_PSKIP || DHP
  memory_size += get_mem2Dint( &p_snd_refFrArr, img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
#endif

  // allocate memory for reference frame in find_snr
  memory_size += get_mem2D ( &imgYRef, img_height, img->width );
  memory_size += get_mem3D ( &imgUVRef, 2, img_height / ( input->chroma_format == 1 ? 2 : 1 ), img->width_cr );

  // allocate memory in structure img
  if ( ( ( img->mb_data ) = ( codingUnit * ) calloc ( ( img->width / MIN_CU_SIZE ) * ( img_height / MIN_CU_SIZE ), sizeof ( codingUnit ) ) ) == NULL )
  {
    no_mem_exit ( "init_global_buffers: img->mb_data" );
  }

  if ( ( ( img->intra_block ) = ( int** ) calloc ( ( j = ( img->width / MIN_CU_SIZE ) * ( img_height / MIN_CU_SIZE ) ), sizeof ( int* ) ) ) == NULL )
  {
    no_mem_exit ( "init_global_buffers: img->intra_block" );
  }

  for ( i = 0; i < j; i++ )
  {
    if ( ( img->intra_block[i] = ( int* ) calloc ( 4, sizeof ( int ) ) ) == NULL )
    {
      no_mem_exit ( "init_global_buffers: img->intra_block" );
    }
  }

// Adaptive frequency weighting quantization  
#if FREQUENCY_WEIGHTING_QUANTIZATION
  Init_QMatrix ();
#endif


#if DMH
#if !MULTIVIEW_CODING
  memory_size += get_mem3Dint ( & ( img->tmp_mv), img_height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 4 );
#endif
#if MH_PSKIP || DHP
  memory_size += get_mem3Dint ( & ( img->p_snd_tmp_mv), img_height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 4 );
#endif
#else
  memory_size += get_mem3Dint ( & ( img->tmp_mv), img_height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 3 );
#endif

  if ( progressive_sequence ) //XZHENG, 200907, LM1.0
  {
    memory_size += get_mem2Dint ( & ( img->ipredmode ), img_height / MIN_BLOCK_SIZE + 2, img->width / MIN_BLOCK_SIZE + 2 );
  }

  get_mem2Dint ( & ( img->predBlock ), ( 1 << input->g_uiMaxSizeInBit ), ( 1 << input->g_uiMaxSizeInBit ) );
  get_mem2Dint ( &img->resiY, ( 1 << (input->g_uiMaxSizeInBit+1) ), ( 1 << (input->g_uiMaxSizeInBit+1 )) );
#if EXTEND_BD
	if ( ( img->quad = ( int* ) calloc ( (1 << input->sample_bit_depth), sizeof ( int ) ) ) == NULL )
#else
	if ( ( img->quad = ( int* ) calloc ( 256, sizeof ( int ) ) ) == NULL )
#endif
  {
    no_mem_exit ( "init_img: img->quad" );
  }
  init ();

  memory_size += get_mem2Dint ( & ( img->fw_refFrArr), img_height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
  memory_size += get_mem2Dint ( & ( img->bw_refFrArr), img_height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
#if !MULTIVIEW_CODING
  memory_size += get_mem3Dint ( & ( img->fw_mv ),img_height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );
  memory_size += get_mem3Dint ( & ( img->bw_mv ),img_height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );
#endif
  // Prediction mode is set to -1 outside the frame, indicating that no prediction can be made from this part
  for ( i = 0; i < img->width / ( MIN_BLOCK_SIZE ) + 2; i++ )
  {
    for ( j = 0; j < img_height / ( MIN_BLOCK_SIZE ) + 2; j++ )
    {
      img->ipredmode[j][i] = -1;
    }
  }

  //by oliver 0512

  img->buf_cycle = input->buf_cycle + 1;

  // allocate frame buffer
#ifdef AVS2_S2_BGLONGTERM
    for ( i = 0; i < 3; i++ )
    {
      if ( i == 0 )
      {
        get_mem2D ( &backgroundReferenceFrame[i], img_height, img->width );
      }
      else
      {
        get_mem2D ( &backgroundReferenceFrame[i], img_height / ( input->chroma_format == 1 ? 2 : 1 ), img->width_cr );
      }
    }
	background_ref = backgroundReferenceFrame;
#endif

#if !MULTIVIEW_CODING
  for ( refnum = 0; refnum <REF_MAXBUFFER; refnum++ )
  {
    for ( i = 0; i < 3; i++ )
    {
      if ( i == 0 )
      {
        get_mem2D ( &referenceFrame[refnum][i], img_height, img->width );
      }
      else
      {
        get_mem2D ( &referenceFrame[refnum][i], img_height / ( input->chroma_format == 1 ? 2 : 1 ), img->width_cr );
      }
    }
  }

  //forward reference frame buffer
  for (j=0; j<REF_MAXBUFFER; j++)
  {
	  ref[j] = referenceFrame[j];
  }

  for ( i = 0; i < REF_MAXBUFFER; i++ )
  {
    get_mem3Dint ( &mvbuf[i], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 2 );
    get_mem2Dint ( &refbuf[i],  img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
  }
#endif

  for ( i = 0; i < REF_MAXBUFFER; i++ )
  {
	  saorate[i] = (double*) calloc (NUM_SAO_COMPONENTS, sizeof(double));
	  if (saorate[i]==NULL)
	  {
		  no_mem_exit ( "init_global_buffers: saorate" );
	  }	 
	  for (j = 0; j<NUM_SAO_COMPONENTS; j++)
	  {
		  saorate[i][j] = 0;
	  }
  }
  // get_mem3DSAOstatdate( &(img->saostatData), (( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)), NUM_SAO_COMPONENTS, NUM_SAO_NEW_TYPES);

  get_mem2DSAOParameter(&(img->saoBlkParams), (( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)), NUM_SAO_COMPONENTS);

  get_mem2DSAOParameter(&img->rec_saoBlkParams, (( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)), NUM_SAO_COMPONENTS);

#if !MULTIVIEW_CODING
  if(( img->cur_saorate = (double*) calloc (NUM_SAO_COMPONENTS, sizeof(double)))==NULL)
  {
	  no_mem_exit ( "init_img: img->cur_saorate" );
  }
#endif
  get_mem2D(&imgY_sao,  img->height, img->width);
  get_mem2D(&(imgUV_sao[0]),  img->height_cr, img->width_cr);
  get_mem2D(&(imgUV_sao[1]),  img->height_cr, img->width_cr);
  return ( memory_size );
}

/*
*************************************************************************
* Function:Free allocated memory of frame size related global buffers
buffers are defined in global.h, allocated memory is allocated in
int init_global_buffers()
* Input:Input Parameters struct inp_par *input, Image Parameters ImageParameters *img
* Output:
* Return:
* Attention:
*************************************************************************
*/

void free_global_buffers ()
{
  int  i, j;
  int img_height = ( vertical_size + img->auto_crop_bottom );

  // Adaptive frequency weighting quantization
#if FREQUENCY_WEIGHTING_QUANTIZATION
  free_QMatrix();
#endif


#ifdef AVS2_S2_BGLONGTERM
#if AVS2_SCENE_CD
  if(background_picture_enable)
#else
  if(background_picture_enable && input->profile_id==0x50)
#endif
  {
	  for(i=0;i<3;i++)
		  free_mem2D(background_frame[i]);
  }
#endif

#if !MULTIVIEW_CODING
  free_mem2D ( imgYPrev );
  free_mem3D ( imgUVPrev, 2 );

  free_mem2Dint( refFrArr );//1105
#endif
#if MH_PSKIP || DHP
  free_mem2Dint( p_snd_refFrArr );
#endif


  free_mem2D ( imgYRef );
  free_mem3D ( imgUVRef, 2 );
  // free mem, allocated for structure img
  if ( img->mb_data       != NULL )
  {
    free ( img->mb_data );
  }

#if M3198_CU8
  j = ( img->width / MIN_CU_SIZE ) * ( img->height / MIN_CU_SIZE );
#else
  j = ( img->width / 16 ) * ( img->height / 16 );
#endif

  for ( i = 0; i < j; i++ )
  {
    free ( img->intra_block[i] );
  }

  free ( img->intra_block );
#if !MULTIVIEW_CODING
  free_mem3Dint ( img->tmp_mv, img_height / MIN_BLOCK_SIZE );
#endif
#if MH_PSKIP || DHP
  free_mem3Dint ( img->p_snd_tmp_mv, img_height / MIN_BLOCK_SIZE);
#endif

  free_mem2Dint ( img->ipredmode );
  free_mem2Dint ( img->resiY );
  free_mem2Dint ( img->predBlock );
  free ( img->quad );

#if !MULTIVIEW_CODING
  free_mem2Dint ( img->fw_refFrArr);
  free_mem2Dint ( img->bw_refFrArr);

  free_mem3Dint ( img->fw_mv, img_height / MIN_BLOCK_SIZE );
  free_mem3Dint ( img->bw_mv, img_height / MIN_BLOCK_SIZE );
#endif

  free_mem2D(imgY_sao);
  free_mem2D(imgUV_sao[0]);
  free_mem2D(imgUV_sao[1]);

  // free_mem3DSAOstatdate(img->saostatData,(( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)), NUM_SAO_COMPONENTS);

  free_mem2DSAOParameter(img->saoBlkParams, (( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)));

  free_mem2DSAOParameter(img->rec_saoBlkParams, (( img->width >> input->g_uiMaxSizeInBit) + (img->width % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)) * (( img->height >> input->g_uiMaxSizeInBit) + (img->height % ( 1<< input->g_uiMaxSizeInBit) ? 1 : 0)));

#if !MULTIVIEW_CODING
  free(img->cur_saorate);
#endif
  for ( i=0; i < REF_MAXBUFFER; i++)
  {
	  if ( saorate[i])
	  {
		  free(saorate[i]);
	  }
  }

#ifdef AVS2_S2_BGLONGTERM
  for( j=0; j<3; j++)
	  free_mem2D(backgroundReferenceFrame[j]);
#endif

#if !MULTIVIEW_CODING
  for ( i = 0; i < REF_MAXBUFFER; i++ )
  {
    for ( j = 0; j < 3; j++ )
    {
      free_mem2D ( referenceFrame[i][j] );
    }
  }

  for ( i = 0; i < REF_MAXBUFFER; i++ )
  {
    free_mem3Dint ( mvbuf[i], img_height / MIN_BLOCK_SIZE );
    free_mem2Dint ( refbuf[i] );
  }
#endif
}



/*!
************************************************************************
* \brief
*    Allocates a stand-alone partition structure.  Structure should
*    be freed by FreePartition();
*    data structures
*
* \par Input:
*    n: number of partitions in the array
* \par return
*    pointer to DataPartition Structure, zero-initialized
*  added by lzhang
************************************************************************
*/

DataPartition *AllocPartition ( int n )
{
  DataPartition *partArr;

  partArr = ( DataPartition * ) calloc ( n, sizeof ( DataPartition ) );

  if ( partArr == NULL )
  {
    snprintf ( errortext, ET_SIZE, "AllocPartition: Memory allocation for Data Partition failed" );
    error ( errortext, 100 );
  }

//   for ( i = 0; i < n; i++ ) // loop over all data partitions
//   {
//     dataPart = & ( partArr[i] );
// 
//     dataPart->bitstream = ( Bitstream * ) calloc ( 1, sizeof ( Bitstream ) );
// 
//     if ( dataPart->bitstream == NULL )
//     {
//       snprintf ( errortext, ET_SIZE, "AllocPartition: Memory allocation for Bitstream failed" );
//       error ( errortext, 100 );
//     }
//   }       //1105

  return partArr;
}

/*!
************************************************************************
* \brief
*    Allocates the slice structure along with its dependent
*    data structures
*
* \par Input:
*    Input Parameters struct inp_par *input,  ImageParameters *img
* \author
* lzhang
************************************************************************
*/
void malloc_slice ()
{
  Slice *currSlice;

  img->currentSlice = ( Slice * ) calloc ( 1, sizeof ( Slice ) );

  if ( ( currSlice = img->currentSlice ) == NULL )
  {
    snprintf ( errortext, ET_SIZE, "Memory allocation for Slice datastruct in NAL-mode %d failed", input->FileFormat );
    error ( errortext, 100 );
  }

  // create all context models
  currSlice->syn_ctx = create_contexts_SyntaxInfo();

  currSlice->max_part_nr = 1;//1105
  currSlice->partArr = AllocPartition ( currSlice->max_part_nr );
}
/*!
************************************************************************
* \brief
*    Memory frees of the Slice structure and of its dependent
*    data structures
*
* \par Input:
*    Input Parameters struct inp_par *input,  ImageParameters *img
* \author
* lzhang
************************************************************************
*/
void free_slice ()
{
  Slice *currSlice = img->currentSlice;

  FreePartition ( currSlice->partArr, 1 );

  if ( 1 )
  {
    // delete all context models
    delete_contexts_SyntaxInfo ( currSlice->syn_ctx );
  }

  free ( img->currentSlice );

  currSlice = NULL;
}
/*!
************************************************************************
* \brief
*    Frees a partition structure (array).
*
* \par Input:
*    Partition to be freed, size of partition Array (Number of Partitions)
*
* \par return
*    None
*
* \note
*    n must be the same as for the corresponding call of AllocPartition
* \author : lzhang
************************************************************************
*/
void FreePartition ( DataPartition *dp, int n )
{
  assert ( dp != NULL );
//  assert ( dp->bitstream != NULL );               //1105
//  assert ( dp->bitstream->streamBuffer != NULL );

  free ( dp );
}


#if MULTIVIEW_CODING
void Init_MultiView_Buffers()
{
	const int maxView = input->view_number;
	int viewNum, refNum;
	int i;

	for (viewNum=0; viewNum<maxView; viewNum++)
	{
		for (refNum=0; refNum<REF_MAXBUFFER; refNum++)
		{
			for (i=0; i<3; i++)
			{
				if (i==0)
				{
					get_mem2D(&multiView_referenceFrame[viewNum][refNum][i], img->height, img->width);

					get_mem2D(&multiView_depth_referenceFrame[viewNum][refNum][i], img->height, img->width);
				}
				else
				{
					get_mem2D(&multiView_referenceFrame[viewNum][refNum][i], img->height_cr, img->width_cr);

					get_mem2D(&multiView_depth_referenceFrame[viewNum][refNum][i], img->height_cr, img->width_cr);

				}
			}

			multiView_ref[viewNum][refNum] = multiView_referenceFrame[viewNum][refNum];
			get_mem3Dint ( &multiView_mvbuf[viewNum][refNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 2 );
			get_mem2Dint ( &multiView_refbuf[viewNum][refNum],  img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );		
			multiView_depth_ref[viewNum][refNum] = multiView_depth_referenceFrame[viewNum][refNum];
			get_mem3Dint ( &multiView_depth_mvbuf[viewNum][refNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 2 );
			get_mem2Dint ( &multiView_depth_refbuf[viewNum][refNum],  img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );

		}
	}




	for (viewNum=0; viewNum<maxView; viewNum++)
	{

		int i,j;


		if(( img->multiView_cur_saorate[viewNum] = (double*) calloc (NUM_SAO_COMPONENTS, sizeof(double)))==NULL)
		{
			no_mem_exit ( "init_img: img->cur_saorate" );
		}
		if(( img->multiView_depth_cur_saorate[viewNum] = (double*) calloc (NUM_SAO_COMPONENTS, sizeof(double)))==NULL)
		{
			no_mem_exit ( "init_img: img->cur_saorate" );
		}

		get_mem2Dint (&multiView_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
#if DMH
		get_mem3Dint(&img->multiView_tmp_mv[viewNum], img->height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 4 );
#else
		get_mem3Dint(&img->multiView_tmp_mv[viewNum], img->height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 3);
#endif

		// allocate memory for temp B-frame motion vector buffer: fw_refFrArr, bw_refFrArr
		get_mem2Dint ( &img->multiView_fw_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
		get_mem2Dint ( &img->multiView_bw_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );

		get_mem3Dint ( & ( img->multiView_fw_mv[viewNum]),img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );
		get_mem3Dint ( & ( img->multiView_bw_mv[viewNum] ),img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );

		get_mem2Dint(&multiView_depth_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE);
		get_mem2Dint ( &img->multiView_depth_fw_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
		get_mem2Dint ( &img->multiView_depth_bw_refFrArr[viewNum], img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE );
#if DMH
		get_mem3Dint(&img->multiView_depth_tmp_mv[viewNum], img->height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 4 );
#else
		get_mem3Dint(&img->multiView_depth_tmp_mv[viewNum], img->height / MIN_BLOCK_SIZE,img->width / MIN_BLOCK_SIZE , 3);
#endif		
		get_mem3Dint ( & ( img->multiView_depth_fw_mv[viewNum]),img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );
		get_mem3Dint ( & ( img->multiView_depth_bw_mv[viewNum] ),img->height / MIN_BLOCK_SIZE, img->width / MIN_BLOCK_SIZE, 3  );


		for(j = 0; j < img->height/MIN_BLOCK_SIZE; j++)	
		{
			for(i = 0; i < img->width/MIN_BLOCK_SIZE; i++)
			{
				multiView_refFrArr[viewNum][j][i] = -1;

				multiView_depth_refFrArr[viewNum][j][i] = -1;

			}
		}



	}



	//after allocating the memory space, reset the pointer, only for coding order equal to 0
	for ( refNum=0; refNum<REF_MAXBUFFER; refNum++)
	{
		ref[refNum]			= multiView_ref[0][refNum];
		//set the reference frame MV address of ith view to mvbuf
		mvbuf[refNum]        = multiView_mvbuf[0][refNum];
		//set the reference frame index address of ith view to refbuf
		refbuf[refNum]       = multiView_refbuf[0][refNum];

	}
	refFrArr = multiView_refFrArr[0];
	img->tmp_mv = img->multiView_tmp_mv[0];
	img->fw_mv  = img->multiView_fw_mv[0];
	img->bw_mv  = img->multiView_bw_mv[0];

	img->cur_saorate = img->multiView_cur_saorate[0];

	img->fw_refFrArr= img->multiView_fw_refFrArr[0];
	img->bw_refFrArr= img->multiView_bw_refFrArr[0];





}

void Free_MultiView_Buffers()
{
	const int maxView = 1;
	int viewNum, refNum;
	int i;

	int img_height = ( vertical_size + img->auto_crop_bottom );

	for (viewNum=0; viewNum<maxView; viewNum++)
	{
		for (refNum=0; refNum<REF_MAXBUFFER; refNum++)
		{
			for (i=0; i<3; i++)
			{
				free_mem2D(multiView_referenceFrame[viewNum][refNum][i]);

				free_mem2D(multiView_depth_referenceFrame[viewNum][refNum][i]);

			}
		}
	}


	for (viewNum=0; viewNum<maxView; viewNum++)
	{
		for (refNum=0; refNum<REF_MAXBUFFER; refNum++)
		{
			free_mem3Dint(multiView_mvbuf[viewNum][refNum], img_height / MIN_BLOCK_SIZE );
			free_mem2Dint(multiView_refbuf[viewNum][refNum]);

			free_mem3Dint(multiView_depth_mvbuf[viewNum][refNum], img_height / MIN_BLOCK_SIZE );
			free_mem2Dint(multiView_depth_refbuf[viewNum][refNum]);

		}
	}


	for (viewNum=0; viewNum<maxView; viewNum++)
	{

		free(img->multiView_cur_saorate[viewNum]);
		free(img->multiView_depth_cur_saorate[viewNum]);

		free_mem2Dint( multiView_refFrArr[viewNum] );
		//	free_mem3Dint ( img->tmp_mv, img_height / MIN_BLOCK_SIZE );
		free_mem3Dint ( img->multiView_tmp_mv[viewNum], img_height / MIN_BLOCK_SIZE );

		// bugfix for video 
		if (img->multiView_fw_mv[viewNum])
		{
			free_mem3Dint(img->multiView_fw_mv[viewNum], img->height / MIN_BLOCK_SIZE );
		}
		if (img->multiView_bw_mv[viewNum])
		{
			free_mem3Dint(img->multiView_bw_mv[viewNum], img->height/MIN_BLOCK_SIZE);
		}

		if(img->multiView_fw_refFrArr[viewNum])
		{
			free_mem2Dint ( img->multiView_fw_refFrArr[viewNum] );
		}
		if(img->multiView_bw_refFrArr[viewNum])
		{
			free_mem2Dint ( img->multiView_bw_refFrArr[viewNum] );
		}

		//depth
		free_mem2Dint( multiView_depth_refFrArr[viewNum] );
		free_mem3Dint ( img->multiView_depth_tmp_mv[viewNum], img_height / MIN_BLOCK_SIZE );
		if (img->multiView_depth_fw_mv[viewNum])
		{
			free_mem3Dint(img->multiView_depth_fw_mv[viewNum], img->height / MIN_BLOCK_SIZE );
		}
		if (img->multiView_depth_bw_mv[viewNum])
		{
			free_mem3Dint(img->multiView_depth_bw_mv[viewNum], img->height/MIN_BLOCK_SIZE);
		}

		if(img->multiView_depth_fw_refFrArr[viewNum])
		{
			free_mem2Dint ( img->multiView_depth_fw_refFrArr[viewNum] );
		}
		if(img->multiView_depth_bw_refFrArr[viewNum])
		{
			free_mem2Dint ( img->multiView_depth_bw_refFrArr[viewNum] );
		}


	}

}

void multiView_report()
{
#define OUTSTRING_SIZE 255
	char string[OUTSTRING_SIZE];
	FILE *p_log;

#ifndef WIN32
	time_t  now;
	struct tm *l_time;
#else
	char timebuf[128];
#endif
	int j;

	if ( img->sequence_end_flag )
	{
		fprintf ( stdout, "Sequence End\n\n" );
	}
	{
		int i;
		float framerate[8] = {24000 / 1001, 24, 25, 30000 / 1001, 30, 50, 60000 / 1001, 60};
		if ( ( int ) ( StatBitsPtr->coded_pic_num - ( StatBitsPtr->time_s + 1 ) *framerate[frame_rate_code - 1] + 0.5 ) == 0 )
		{
			StatBitsPtr->total_bitrate[StatBitsPtr->time_s++] = StatBitsPtr->bitrate;
			StatBitsPtr->bitrate = 0;
		}
		StatBitsPtr->total_bitrate[StatBitsPtr->time_s - 1] += 32;
		printf ( "Second(s)\tBitrate(bit/s)\n" );
		for ( i = 0; i < StatBitsPtr->time_s; i++ )
		{
			printf ( " %3d\t\t %d\n", i, StatBitsPtr->total_bitrate[i] );
		}

		if ( StatBitsPtr->time_s == 0 )
		{
			printf ( " %3d\t\t %d\n", 0, StatBitsPtr->total_bitrate[0] );
		}
	}
	for (j=0; j<input->view_number; j++)
	{
		StatBitsPtr = &multiView_StatBits[j];
		snr			= &multiView_snrs[j];

		fprintf ( stdout, "-------------------- Average SNR for View_%d ------------------------------\n", j );
		fprintf ( stdout, " SNR Y(dB)           : %5.2f\n", snr->snr_ya );
		fprintf ( stdout, " SNR U(dB)           : %5.2f\n", snr->snr_ua );
		fprintf ( stdout, " SNR V(dB)           : %5.2f\n", snr->snr_va );
		fprintf ( stdout, " Total decoding time : %.3f sec \n", tot_time * 0.001 );
		fprintf ( stdout, "---------------------------------------------------------------------------\n" );

		if (input->bUseDepth)
		{
			StatBitsPtr = &multiView_depth_StatBits[j];
			snr			= &multiView_depth_snrs[j];

			fprintf ( stdout, "-------------------- Average SNR for Depth_%d ------------------------------\n", j );
			fprintf ( stdout, " SNR Y(dB)           : %5.2f\n", snr->snr_ya );
			fprintf ( stdout, " SNR U(dB)           : %5.2f\n", snr->snr_ua );
			fprintf ( stdout, " SNR V(dB)           : %5.2f\n", snr->snr_va );
			fprintf ( stdout, " Total decoding time : %.3f sec \n", tot_time * 0.001 );
			fprintf ( stdout, "---------------------------------------------------------------------------\n" );
		}

	}


	fprintf ( stdout, " Exit RD %s decoder, ver %s ", RD, VERSION );
	fprintf ( stdout, "\n" );

	textureDepth_report(0);
	if (input->bUseDepth)
	{
		textureDepth_report(1);
	}
}

void textureDepth_report(int isDepth)
{
	int i;
	char timebuf[128];
	char string[OUTSTRING_SIZE];

	if (isDepth)
	{
		snprintf ( string, OUTSTRING_SIZE, "%s", DEPTH_LOGFILE );
	}
	else 
	{
		snprintf ( string, OUTSTRING_SIZE, "%s", VIEW_LOGFILE );
	}

	if ( ( p_log = fopen ( string, "r" ) ) == 0 )        // check if file exist
	{
		if ( ( p_log = fopen ( string, "a" ) ) == 0 )
		{
			snprintf ( errortext, ET_SIZE, "Error open file %s for appending", string );
			error ( errortext, 500 );
		}
		else                                              // Create header to new file
		{
			fprintf ( p_log, " ------------------------------------------------------------------------------------------\n" );
			fprintf ( p_log, "|  Decoder statistics. This file is made first time, later runs are appended               |\n" );
			fprintf ( p_log, " ------------------------------------------------------------------------------------------ \n" );
			fprintf ( p_log, "| Date  | Time  |    Sequence        |#Img|Format|SNRY 1|SNRU 1|SNRV 1|SNRY N|SNRU N|SNRV N|\n" );
			fprintf ( p_log, " ------------------------------------------------------------------------------------------\n" );
		}
	}
	else
	{
		fclose ( p_log );
		p_log = fopen ( string, "a" );              // File exist,just open for appending
	}

#ifdef WIN32
	_strdate ( timebuf );
	fprintf ( p_log, "| %1.5s |", timebuf );

	_strtime ( timebuf );
	fprintf ( p_log, " % 1.5s |", timebuf );
#else
	now = time ( ( time_t * ) NULL ); // Get the system time and put it into 'now' as 'calender time'
	time ( &now );
	l_time = localtime ( &now );
	strftime ( string, sizeof string, "%d-%b-%Y", l_time );
	fprintf ( p_log, "| %1.5s |", string );

	strftime ( string, sizeof string, "%H:%M:%S", l_time );
	fprintf ( p_log, "| %1.5s |", string );
#endif

	fprintf ( p_log, "%20.20s|", input->infile );

	fprintf ( p_log, "%3d |", img->number );

	for (i=0; i<input->view_number; i++)
	{
		snr = isDepth ? &multiView_depth_snrs[i] : &multiView_snrs[i];
		fprintf ( p_log, "%6.3f|", snr->snr_y1 );
		fprintf ( p_log, "%6.3f|", snr->snr_u1 );
		fprintf ( p_log, "%6.3f|", snr->snr_v1 );
		fprintf ( p_log, "%6.3f|", snr->snr_ya );
		fprintf ( p_log, "%6.3f|", snr->snr_ua );
		fprintf ( p_log, "%6.3f|\n", snr->snr_va );

		snprintf ( string, OUTSTRING_SIZE, "%s", DATADECFILE );
		p_log = fopen ( string, "a" );

		if ( Bframe_ctr != 0 ) // B picture used
		{
			fprintf ( p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5d "
				"%2.2f %2.2f %2.2f %5d "
				"%2.2f %2.2f %2.2f %5d %.3f\n",
				img->number, 0, img->qp,
				snr->snr_y1,
				snr->snr_u1,
				snr->snr_v1,
				0,
				0.0,
				0.0,
				0.0,
				0,
				snr->snr_ya,
				snr->snr_ua,
				snr->snr_va,
				0,
				( double ) 0.001 * tot_time / ( img->number + Bframe_ctr - 1 ) );
		}
		else
		{
			fprintf ( p_log, "%3d %2d %2d %2.2f %2.2f %2.2f %5d "
				"%2.2f %2.2f %2.2f %5d "
				"%2.2f %2.2f %2.2f %5d %.3f\n",
				img->number, 0, img->qp,
				snr->snr_y1,
				snr->snr_u1,
				snr->snr_v1,
				0,
				0.0,
				0.0,
				0.0,
				0,
				snr->snr_ya,
				snr->snr_ua,
				snr->snr_va,
				0,
				( double ) 0.001 * tot_time / img->number );
		}
	}


	fclose ( p_log );
}
#endif

#if MULTIVIEW_CODING
void initFileNames(char* dstStr, char* srcStr, int currView)
{
	unsigned int length = strlen(srcStr);
	char* TempSplit;

	TempSplit = strtok(srcStr, ".yuv");
	length = strlen(TempSplit);
	strcpy(dstStr, TempSplit);
	dstStr[length++] = '_';
	dstStr[length++] = (char)('0'+currView);
	dstStr[length] = '\0';
	strcat(dstStr, ".yuv");
}
#endif